package ua.edu.nuos.jeetraining2012.cms.util.template.course;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import ua.edu.nuos.jeetraining2012.cms.dto.UpcomingHomeWorkDTO;
import ua.edu.nuos.jeetraining2012.cms.entity.CourseEntity;
import ua.edu.nuos.jeetraining2012.cms.entity.UserEntity;
import ua.edu.nuos.jeetraining2012.cms.service.Course;
import ua.edu.nuos.jeetraining2012.cms.service.HomeWork;
import ua.edu.nuos.jeetraining2012.cms.util.LocaleWrapper;
import ua.edu.nuos.jeetraining2012.cms.util.template.layout.DefaultLayoutTemplate;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.*;


/**
 * Class implementation {@link ua.edu.nuos.jeetraining2012.cms.util.template.Templatable} for indexAction of a CourseServlet.
 */
public class MyCoursesTemplate extends DefaultLayoutTemplate {

    /** Define logger */
    final private static Logger logger = org.slf4j.LoggerFactory.getLogger(MyCoursesTemplate.class);

    /** Define Course logic. */
    private Course courseService;

    /** Define user id. */
    private String userId = null;

    /** Define HW service */
    private HomeWork homeWorkService;

    //Constructor
    public MyCoursesTemplate() {
        super();
        logger.debug("MyCoursesTemplate() - invocation.");
        templateName = "/view/course/mycourses.ftl";

        try {
            InitialContext ic = new InitialContext();
            courseService = (Course) ic.lookup("java:module/Course");
            logger.debug("Course service injected successful");
            homeWorkService = (HomeWork) ic.lookup("java:module/HomeWork");
            logger.debug("Homework service injected successful");
        } catch (NamingException e) {
            logger.warn("Can't lookup Course class - invocation.");
            logger.debug("IndexTemplate() - invocation finish width NamingException" + e.getMessage());
        }

        final Subject subject = SecurityUtils.getSubject();
        if (subject != null && subject.isAuthenticated()) {
            UserEntity user = (UserEntity) subject.getSession().getAttribute("user");
            if (user != null) {
                userId = user.getId();
            }
        }
    }

    //Overrides
    @Override
    public Map<String, Object> getMap() {
        logger.debug("Method getMap() - invocation.");

        Map<String, Object> parent = super.getMap();
        Map<String, Object> map = (parent == null)
                ? new HashMap<String, Object>()
                : parent;

        logger.debug("Parent map is {}", map);

        Map<String, Object> innerMap = new HashMap<>();
        innerMap.put("i18n", getI18nMap());

        List<CourseEntity> availableCourses = courseService.getStudentsCourses(userId);
        innerMap.put("content", prepareCourses(availableCourses));

        List<UpcomingHomeWorkDTO> upcomingCourseHW = homeWorkService.getAllUpcomingStudentHw(availableCourses);

        map.put("currentController", "course");
        map.put("currentAction", "mycourses");
        map.put("courses", innerMap);
        map.put("upcomingHW", upcomingCourseHW);
        return map;
    }

    /**
     * Method prepare List with data about the available Courses, that will use by index.ftl
     *
     * @param courses the List of available entities instance
     * @return prepared List
     */
    private List<Map<String, Object>> prepareCourses(List<CourseEntity> courses) {
        logger.debug("Method prepareCourse(courses) - invocation.");
        List<Map<String, Object>> prepareCourses = new ArrayList<>();
        Map<String, Object> course;

        for (CourseEntity entity : courses) {
            course = new HashMap<>();
            course.put("id", entity.getId());
            course.put("title", entity.getTitle());
            course.put("startDate", entity.getStartDate());
            course.put("finishDate", entity.getFinishDate());
            course.put("shortDescription", entity.getShortDescription());
            course.put("logoURL", entity.getLogoURL());
            course.put("isEnrolled", true);
            logger.debug("course {}", course);
            prepareCourses.add(course);
        }
        logger.debug("Method prepareCourse(courses) - Finish.");
        return prepareCourses;
    }

    /**
     * Define i18n for courses.
     *
     * @return Augmented i18n Map.
     */
    protected Map<String, Object> getI18nMap() {
        logger.debug("getI18nMap() - started.");

        ResourceBundle i18n = null;
        try {
            i18n = LocaleWrapper.getBundle("mycourse", locale);
        } catch (MissingResourceException e) {
            logger.debug("Can't find resource Bundle - " + e.getMessage());
        } catch (NullPointerException e) {
            logger.debug("finish with NPE baseName or locale is null - " + e.getMessage());
        }

        Map<String, Object> i18nMapCourses = new HashMap<>();
        i18nMapCourses.put("header", i18n.getString("header"));
        i18nMapCourses.put("unenroll_button_label", i18n.getString("unenroll-button-label"));
        i18nMapCourses.put("no_courses_message", i18n.getString("no-courses-message"));
        i18nMapCourses.put("a_course_list_label", i18n.getString("a-course-list-label"));
        i18nMapCourses.put("hw_block_header", i18n.getString("hw_block_header"));
        i18nMapCourses.put("hw_link_label", i18n.getString("hw_link_label"));
        i18nMapCourses.put("hw_okuntil_label", i18n.getString("hw_okuntil_label"));
        i18nMapCourses.put("show_materials_button_label", i18n.getString("show_materials_button_label"));

        logger.debug("getI18nMap() - finished");
        return i18nMapCourses;
    }
}
